#pragma once

#include "Image.h"
#include "Color.h"

enum fillMode
{
	alternateFill,
	windingFill
};

enum wrapMode
{
	tileWrap,      
	tileFlipXWrap, 
	tileFlipYWrap, 
	tileFlipXYWrap,
	clampWrap
};

enum brushType
{
	solidBrush,
	textureBrush,
	gradientBrush,
	hatchBrush
};

class Brush
{
public:
	virtual ~Brush(){}
	virtual brushType GetType() const  = 0;
	virtual Brush* Clone() const = 0;

protected:
	Brush(){}
};

class SolidBrush : public Brush
{
public:
	SolidBrush(const Color& color)
	{
		m_color = color;
	}
	const Color& GetColor() const {return m_color;}
	brushType GetType() const {return solidBrush;}
	SolidBrush* Clone()const 
	{
		return new SolidBrush(m_color);
	}

private:
	Color m_color;
};


class TextureBrush : public Brush
{
public:
	TextureBrush(Image* image,wrapMode wrap=tileWrap)
	{
		m_image = image;
		m_wrap = wrap;
	}

	Image* GetImage() const {return m_image;}
	wrapMode GetWrapMode() const {return m_wrap;}
	brushType GetType() const {return textureBrush;}
	TextureBrush* Clone()const 
	{
		return new TextureBrush(m_image,m_wrap);
	}

private:
	Image* m_image;
	wrapMode m_wrap;
};

class GradientBrush : public Brush
{
	typedef std::vector<float> Factors;
	typedef std::vector<float> Positions;

public:
	enum gradienStyle
	{
		horizontalLinear,
		verticalLinear,
		forwardDiagonalLinear,
		backwardDiagonalLinear,
	};
	brushType GetType() const {return gradientBrush;}
	GradientBrush* Clone()const 
	{
		GradientBrush* newbrush = new GradientBrush;
		newbrush->m_colors = m_colors;
		newbrush->m_factors = m_factors;
		newbrush->m_positions = m_positions;
		return newbrush;
	}
private:
	Colors m_colors;
	Factors m_factors;
	Positions m_positions;
};

class HatchBrush : public Brush
{
public:
	enum hatchStyle
	{
		horizontalHatch,                   
		verticalHatch,                     
		forwardDiagonalHatch,              
		backwardDiagonalHatch,             
		crossHatch,                        
		diagonalCrossHatch            
	};
	HatchBrush(hatchStyle hatchStyle,const Color& foregroundColor,const Color& backgroundColor=Color())
	{
		m_hatchStyle = hatchStyle;
		m_foregroundColor = foregroundColor;
		m_backgroundColor = backgroundColor;
	}
	hatchStyle GetHatchStyle() const {return m_hatchStyle;}
	const Color& GetForegroundColor() const{return m_foregroundColor;}
	const Color& GetBackgroundColor() const{return m_backgroundColor;}

	brushType GetType() const {return hatchBrush;}
	HatchBrush* Clone()const 
	{
		return new HatchBrush(m_hatchStyle,m_foregroundColor,m_backgroundColor);
	}
private:
	Color m_foregroundColor;
	Color m_backgroundColor;
	hatchStyle m_hatchStyle;
};